
#ifndef MouseState_h
#define MouseState_h

#include <CSharpPropertyMethods.h>

#include <System/Object.h>
#include <System/IntPtr.h>

#include <Riccsson/Xna/Framework/Input/ButtonState.h>

namespace Riccsson
{
	namespace Xna
	{
		namespace Framework
		{
			namespace Input
			{
				// Summary:
				//     Represents the state of a mouse input device, including mouse cursor position
				//     and buttons pressed. Reference page contains links to related code samples.
				struct MouseState
				{
					union BitPack
					{
						ulong coded;
						struct
						{
							short x;
							short y;
							short wheel;
							uint leftButton : 1;
							uint middleButton : 1;
							uint rightButton : 1;
							uint xButton1 : 1;
							uint xButton2 : 1;
						} packed;
					};

					BitPack _coded;
					
					PROP3GET(MouseState, ButtonState, LeftButton);
					PROP3GET(MouseState, ButtonState, MiddleButton);
					PROP3GET(MouseState, ButtonState, RightButton);
					PROP3GET(MouseState, int, ScrollWheelValue);
					PROP3GET(MouseState, int, X);
					PROP3GET(MouseState, ButtonState, XButton1);
					PROP3GET(MouseState, ButtonState, XButton2);
					PROP3GET(MouseState, int, Y);

					COPY_CONSTRUCTOR(MouseState)
					{
						PROP3GET_INIT_COPY(MouseState, ButtonState, LeftButton);
						PROP3GET_INIT_COPY(MouseState, ButtonState, MiddleButton);
						PROP3GET_INIT_COPY(MouseState, ButtonState, RightButton);
						PROP3GET_INIT_COPY(MouseState, int, ScrollWheelValue);
						PROP3GET_INIT_COPY(MouseState, int, X);
						PROP3GET_INIT_COPY(MouseState, ButtonState, XButton1);
						PROP3GET_INIT_COPY(MouseState, ButtonState, XButton2);
						PROP3GET_INIT_COPY(MouseState, int, Y);

						_coded = other._coded;
					}

					public: MouseState()		
						: PROP3GET_INIT(MouseState, LeftButton)
						, PROP3GET_INIT(MouseState, MiddleButton)
						, PROP3GET_INIT(MouseState, RightButton)
						, PROP3GET_INIT(MouseState, ScrollWheelValue)
						, PROP3GET_INIT(MouseState, X)
						, PROP3GET_INIT(MouseState, XButton1)
						, PROP3GET_INIT(MouseState, XButton2)
						, PROP3GET_INIT(MouseState, Y)
					{
					}

					//
					// Summary:
					//     Initializes a new instance of the MouseState class.
					//
					// Parameters:
					//   x:
					//     Horizontal mouse position.
					//
					//   y:
					//     Vertical mouse position.
					//
					//   scrollWheel:
					//     Mouse scroll wheel value.
					//
					//   leftButton:
					//     Left mouse button state.
					//
					//   middleButton:
					//     Middle mouse button state.
					//
					//   rightButton:
					//     Right mouse button state.
					//
					//   xButton1:
					//     XBUTTON1 state.
					//
					//   xButton2:
					//     XBUTTON2 state.
					public: MouseState(int x, int y, int scrollWheel, ButtonState leftButton, ButtonState middleButton, ButtonState rightButton, ButtonState xButton1, ButtonState xButton2)		
						: PROP3GET_INIT(MouseState, LeftButton)
						, PROP3GET_INIT(MouseState, MiddleButton)
						, PROP3GET_INIT(MouseState, RightButton)
						, PROP3GET_INIT(MouseState, ScrollWheelValue)
						, PROP3GET_INIT(MouseState, X)
						, PROP3GET_INIT(MouseState, XButton1)
						, PROP3GET_INIT(MouseState, XButton2)
						, PROP3GET_INIT(MouseState, Y)
					{
						_coded.packed.x = (short)x;
						_coded.packed.y = (short)y;
						_coded.packed.wheel = (short)scrollWheel;
						_coded.packed.leftButton = (uint)leftButton;
						_coded.packed.middleButton = (uint)middleButton;
						_coded.packed.rightButton = (uint)rightButton;
						_coded.packed.xButton1 = (uint)xButton1;
						_coded.packed.xButton2 = (uint)xButton2;
					}

					// Summary:
					//     Returns the state of the left mouse button.
					public: PROP3_GET(ButtonState, LeftButton)
					{
						return (ButtonState)_coded.packed.leftButton;
					}

					//
					// Summary:
					//     Returns the state of the middle mouse button.
					public: PROP3_GET(ButtonState, MiddleButton)
					{
						return (ButtonState)_coded.packed.middleButton;
					}

					//
					// Summary:
					//     Returns the state of the right mouse button.
					public: PROP3_GET(ButtonState, RightButton)
					{
						return (ButtonState)_coded.packed.rightButton;
					}

					//
					// Summary:
					//     Gets the cumulative mouse scroll wheel value since the game was started.
					public: PROP3_GET(int, ScrollWheelValue)
					{
						return (int)_coded.packed.wheel;
					}

					//
					// Summary:
					//     Specifies the horizontal position of the mouse cursor. Reference page contains
					//     links to related code samples.
					public: PROP3_GET(int, X)
					{
						return (int)_coded.packed.x;
					}

					//
					// Summary:
					//     Returns the state of XBUTTON1.
					public: PROP3_GET(ButtonState, XButton1)
					{
						return (ButtonState)_coded.packed.xButton1;
					}

					//
					// Summary:
					//     Returns the state of XBUTTON2.
					public: PROP3_GET(ButtonState, XButton2)
					{
						return (ButtonState)_coded.packed.xButton2;
					}

					//
					// Summary:
					//     Specifies the vertical position of the mouse cursor. Reference page contains
					//     links to related code samples.
					public: PROP3_GET(int, Y)
					{
						return (int)_coded.packed.y;
					}

					// Summary:
					//     Returns a value that indicates whether the current instance is equal to a
					//     specified object.
					//
					// Parameters:
					//   obj:
					//     Object with which to make the comparison.
					public: override bool Equals(System::object* obj)
					{
						throw System::NotImplementedException();
					}

					//
					// Summary:
					//     Gets the hash code for this instance.
					public: override int GetHashCode()
					{
						return (int)_coded.coded;
					}

					//
					// Summary:
					//     Retrieves a string representation of this object.
					public: override GC_PTR<System::string> ToString()
					{
						throw System::NotImplementedException();
					}
				};
				
				// Summary:
				//     Determines whether two MouseState instances are not equal.
				//
				// Parameters:
				//   left:
				//     Object on the left of the equal sign.
				//
				//   right:
				//     Object on the right of the equal sign.
				inline static bool operator !=(MouseState left, MouseState right)
				{
					return left._coded.coded != right._coded.coded;
				}

				//
				// Summary:
				//     Determines whether two MouseState instances are equal.
				//
				// Parameters:
				//   left:
				//     Object on the left of the equal sign.
				//
				//   right:
				//     Object on the right of the equal sign.
				inline static bool operator ==(MouseState left, MouseState right)
				{
					return left._coded.coded == right._coded.coded;
				}
			}
		}
	}
}

#endif